<script lang="ts" setup>
import type { DefApplicationModel } from '#/api';
import type { BaseRoleModel } from '#/api/basic/system/model/baseRoleModel';

import { onMounted, reactive } from 'vue';

import { isEmptyOrUnDef } from '@vben/utils';

import { Button, Card, Empty } from 'ant-design-vue';

import { DefApplicationApi } from '#/api';
import { BaseRoleApi } from '#/api/basic/system/baseRole';
import { DataTypeEnum, RoleCategoryEnum } from '#/enums/base';
import { PermCode } from '#/enums/perm';
import { useMessage } from '#/hooks/web/useMessage';
import { eachTree } from '#/utils/helper/treeHelper';

import ResourceTree from './resource-tree.vue';

defineOptions({
  name: 'ApplicationTrees',
  inheritAttrs: false,
});
const { createMessage } = useMessage();

interface State {
  applicationResourceList: DefApplicationModel.ApplicationResourceResultVO[];
  confirmLoading: boolean;
  appResMap: Record<string, string[]>;
  defaultExpandedNames: string[];
  title: string;
  category: RoleCategoryEnum;
  showSaveBtn: boolean;
  role?: BaseRoleModel.BaseRoleResultVO;
}

const formData = reactive<BaseRoleModel.BaseRoleResourceRelSaveVO>({
  roleId: '',
  applicationResourceMap: {},
});

const permCode = PermCode.basic.system.baseRole;
const state = reactive<State>({
  applicationResourceList: [],
  confirmLoading: false,
  appResMap: {},
  defaultExpandedNames: [],
  category: RoleCategoryEnum.FUNCTION,
  title: '请选择角色',
  showSaveBtn: false,
});
const itemRefs: Record<string, any> = {};

onMounted(async () => {
  state.applicationResourceList =
    await DefApplicationApi.findAvailableApplicationResourceList();

  state.defaultExpandedNames = state.applicationResourceList.map(
    (item) => item.defApplication.id as string,
  );
});

async function getData() {
  const appResourceMap: Record<string, string[]> = {};

  for (const item of state.applicationResourceList) {
    const itemRef = itemRefs[item.defApplication.id as string];
    if (!itemRef) {
      continue;
    }

    const checkedKeys = itemRef.treeRef.getCheckedKeys();
    const checkeds = itemRef.treeRef?.getCheckStrictly()
      ? (checkedKeys as any).checked
      : checkedKeys;

    if (itemRef.state.checkAll || itemRef.state.indeterminate) {
      appResourceMap[item.defApplication.id as string] = checkeds;
    } else {
      appResourceMap[item.defApplication.id as string] = [];
    }
  }
  formData.applicationResourceMap = appResourceMap;
  return formData;
}

async function load(role: BaseRoleModel.BaseRoleResultVO) {
  if (role && role.id) {
    state.category = role.category as RoleCategoryEnum;
    state.role = role;

    state.applicationResourceList = await (state.category ===
    RoleCategoryEnum.DATA_SCOPE
      ? DefApplicationApi.findAvailableApplicationDataScopeList()
      : DefApplicationApi.findAvailableApplicationResourceList());
    state.defaultExpandedNames = state.applicationResourceList.map(
      (item) => item.defApplication.id as string,
    );

    state.applicationResourceList.forEach((value) => {
      const { resourceList } = value;
      const keys = [] as string[];
      eachTree(
        resourceList,
        (item, parent) => {
          keys.push(item.id);
          item.key = item.id;
          item.title = item.name;
          item.keyLinks = [...(parent.keyLinks || []), item.id];
          item.slots = { title: 'title' };
          return item;
        },
        {},
      );

      value.allKeys = keys;
    });

    state.showSaveBtn = DataTypeEnum.SYSTEM !== role.type;

    formData.roleId = role.id;

    if (state.category === RoleCategoryEnum.DATA_SCOPE) {
      state.title = `【${role.name}】拥有的数据权限`;
      state.appResMap = await BaseRoleApi.findResourceDataScopeIdByRoleId(
        role.id,
      );
    } else {
      state.title = `【${role.name}】拥有的应用资源`;
      state.appResMap = await BaseRoleApi.findResourceIdByRoleId(role.id);
    }
  } else {
    state.title = '请选择角色';
    formData.roleId = '';
    state.showSaveBtn = false;
    const appResourceMap: Record<string, string[]> = {};
    for (const item of state.applicationResourceList) {
      appResourceMap[item.defApplication.id as string] = [];
    }
    state.appResMap = appResourceMap;
  }
}

async function handleSubmit() {
  try {
    state.confirmLoading = true;
    const params = await getData();
    if (state.showSaveBtn) {
      await BaseRoleApi.saveRoleResource(params);

      await load(state.role as BaseRoleModel.BaseRoleResultVO);
      createMessage.success('配置成功');
    } else {
      createMessage.warning('请选择角色');
    }
  } finally {
    state.confirmLoading = false;
  }
}

defineExpose({ load });
</script>

<template>
  <Card :title="state.title" class="ml-1">
    <template #extra>
      <Button
        v-if="state.showSaveBtn"
        v-hasAnyPermission="[permCode.bindResource]"
        class="!ml-4"
        type="primary"
        :loading="state.confirmLoading"
        @click="handleSubmit"
      >
        {{ $t('common.saveText') }}
      </Button>
      <span v-else-if="isEmptyOrUnDef(formData.roleId)" style="color: red">
        请选择角色
      </span>
      <span v-else style="color: red">系统角色拥有全部权限</span>
    </template>
    <ResourceTree
      v-for="item in state.applicationResourceList"
      :key="item.defApplication.id"
      :ref="(el) => (itemRefs[item.defApplication.id as string] = el)"
      :application="item.defApplication"
      :all-keys="item.allKeys"
      :resource-list="item.resourceList"
      :checked-keys="{
        checked: state.appResMap[item.defApplication.id] as string[],
        halfChecked: [],
      }"
    />
    <Empty v-if="state.applicationResourceList.length === 0" />
  </Card>
</template>
